
package com.epam.android.training.level1.rss.parser;

import com.epam.android.training.level1.rss.FeedBo;
import com.epam.android.training.level1.rss.RssParserException;
import com.epam.android.training.level1.util.IOUtils;

import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

/**
 * @author Anton Novikov
 */
public abstract class BaseSaxFeedParser extends DefaultHandler implements FeedParser {
  protected static final String TAG = "FeedParser";

  private final URL feedUrl;

  private final StringBuilder builder;

  protected BaseSaxFeedParser(String feedUrl) throws MalformedURLException {
    this(new URL(feedUrl));
  }

  /**
   * Creates an instance of BaseFeedParser.
   */
  protected BaseSaxFeedParser(URL feedUrl) {
    this.feedUrl = feedUrl;
    this.builder = new StringBuilder();
  }

  protected abstract FeedBo obtainResult();

  @Override
  public FeedBo parse() throws RssParserException {
    SAXParserFactory parserFactory = SAXParserFactory.newInstance();
    InputStream feedStream = null;
    try {
      feedStream = getFeedStream();
      SAXParser parser = parserFactory.newSAXParser();
      parser.parse(feedStream, this);
    } catch (ParserConfigurationException e) {
      throw new RssParserException("Unable to prepare feed parser.", e);
    } catch (SAXException e) {
      throw new RssParserException("Error while feed parsing.", e);
    } catch (IOException e) {
      throw new RssParserException("Unable to obtain feed stream.", e);
    } finally {
      IOUtils.close(feedStream);
    }
    FeedBo feed = obtainResult();
    if (feed != null) {
      feed.setFeedUrl(feedUrl);
    }
    return feed;
  }

  protected final InputStream getFeedStream() throws IOException {
    return feedUrl.openStream();
  }

  @Override
  public void characters(char[] ch, int start, int length) throws SAXException {
    builder.append(ch, start, length);
  }

  protected String getText() {
    return builder.toString().trim();
  }

  protected void clearCache() {
    builder.setLength(0);
  }
}
